#ifndef RENDERINGLISTNODE_H_INCLUDED
#define RENDERINGLISTNODE_H_INCLUDED

//predecl
namespace cvRenderInterface	{ class Renderinglayer; };
namespace cvObjects	{ class BaseCameraObject; };

// includes.
#include <boost/intrusive/list.hpp>
#include "CollectionTypes.h"
#include <ObjectSubsystem/BaseCameraObject.h>

namespace cvRenderInterface
{
	/**
		@class the base class for renderer objects and classes.
	*/
	class DrawlistNode
	{
		public:
			/* Construction. DrawlistNode uses named-constructors idiom.*/
			///static DrawlistNode * create(); // <must be defined by derived.>

			// like ObjectSubSystem::BaseObject, renderer objects are also destructed using virtual destrtoy();
			virtual void destroy() =0;

			/// Drawing order #3
			// in 3D, we talk about 'Z-order', but in 2D there is no such concept. Thus "DrawPriority"
			virtual void setDrawPriority( int level );
			virtual float drawPriority() const;

			/// Separates node into 'sub-layer'. processCollections() stage will never
			/// try place nodes into same CollectionNode that have diffrent sub-layer group-id.
			/// Default layer is zero, which can be moved into any other layer.
			virtual void setDrawGroup( size_t id );
			size_t drawGroup() const;

			// is node an singleshot node?
			virtual const bool isSingleshot() const =0;

			/// Collections #4
			// is node an CollectionNode?
			virtual const bool isCollection() const =0;
			// CollectionNodes && Renderables both return same type: they belong into same group.
			virtual const Collection collectionType() const =0;

			/// Collect #5
			// Filter nodes out that are not visible on the camera.
			// processRender() consumes the internaly generated data.
			virtual void processCollect(const cvObjects::BaseCameraObject * camera) =0;

			/// Transfer #6
			// We calculate stuff, vetexes, ect. and transfer the results into OpenGL primitives. (ie. into GPU memory, serialization)
			virtual void processTransfer() =0;

			/// Render #7
			// Draw the data.
			virtual void processRender() =0;

			/// Locks the node.
			virtual void lockTransfer(bool enable);

			/// Hooks to various containers
			boost::intrusive::list_member_hook<> m_renderlisthook;

		protected:
			// All renderer objects are essentially allocated from heap, so hide actual constructors:
			// When node is created, its layer is set to the layer which IRenderer::getActiveLayer() returns.
			DrawlistNode();
			~DrawlistNode();	// because we use virtual destroy(), we do not need actual virtual destructor.

			mutable float m_draworder;	// the drawing priority of the node. near 0.0 nodes are drawn first to 1.0 which are drawn last.
			size_t m_drawgroup;	// nodes having same id are draw in batch.
			bool m_lockedtransfer;
			Renderinglayer * m_layer;	// The rendering layer that owns the node.
		private:
			void * operator new(size_t);
			void operator delete(void*);
			void * operator new[] (size_t);	//<never implement!>
			void operator delete[] (void*);	//<never implement!>
	};


	/// Rendering spatialhashmap type. (todo)

	/// help func for sorting the DrawlistNodes (only DrawlistNode::m_draworder attribute)
	bool compare_drawnodes(const DrawlistNode & left, const DrawlistNode & right);

};


#endif // RENDERINGLISTNODE_H_INCLUDED
